package com.stone.design.mode.chain.filter;

/**
 * 责任链构建工厂，参考 dubbo 实现
 *
 * @author wenpan 2022/11/20 10:22 下午
 */
public final class FilterChainFactory {

    private FilterChainFactory() {
    }

    /**
     * 构建责任链
     *
     * @param target  目标节点
     * @param filters 对目标节点的过滤链
     * @return com.stone.design.mode.chain.filter.FilterChain<T>
     * @author wenpan 2022/11/20 10:28 下午
     */
    @SafeVarargs
    public static <T> FilterChain<T> buildFilterChain(Invoker<T> target, Filter<T>... filters) {
        // 创建一条责任链
        FilterChain<T> filterChain = new FilterChain<>();
        Invoker<T> last = target;
        // 倒序遍历每一个节点
        for (int i = filters.length - 1; i >= 0; i--) {
            Invoker<T> next = last;
            Filter<T> filter = filters[i];
            last = new Invoker<T>() {
                @Override
                public void invoke(T context) {
                    // 将filter对象和下一个节点invoker（next）传递到invoker内部，
                    // invoke方法被吊起时便能执行doFilter逻辑，并且正在执行中的Invoker也能正确的感知到他的下一个Invoker
                    filter.doFilter(context, next);
                }
            };
        }
        // 责任链头节点赋值
        filterChain.setHead(last);
        return filterChain;
    }

}
